package com.xmhmyh.generalframework.framework.uid;


import com.xmhmyh.generalframework.framework.uid.utils.DockerUtils;
import com.xmhmyh.generalframework.framework.uid.utils.NetUtils;
import com.xmhmyh.generalframework.framework.uid.worker.WorkerIdAssigner;
import com.xmhmyh.generalframework.framework.uid.worker.WorkerNodeType;
import com.xmhmyh.generalframework.project.sys.entity.WorkerNode;
import com.xmhmyh.generalframework.project.sys.mapper.WorkerNodeMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;

@Slf4j
public class DisposableWorkerIdAssigner implements WorkerIdAssigner {


    @Resource
    private WorkerNodeMapper workerNodeMapper;

    /**
     * Assign worker id base on database.<p>
     * If there is host name & port in the environment, we considered that the node runs in Docker container<br>
     * Otherwise, the node runs on an actual machine.
     *
     * @return assigned worker id
     */
    @Override
    @Transactional
    public long assignWorkerId() {
        // build worker node entity
        WorkerNode workerNode = buildWorkerNode();

        // add worker node for new (ignore the same IP + PORT)
        workerNodeMapper.insert(workerNode);
        log.info("Add worker node:" + workerNode);

        return workerNode.getId();
    }

    /**
     * Build worker node entity by IP and PORT
     */
    private WorkerNode buildWorkerNode() {
        WorkerNode workerNode = new WorkerNode();
        if (DockerUtils.isDocker()) {
            workerNode.setType(WorkerNodeType.CONTAINER.value());
            workerNode.setHostName(DockerUtils.getDockerHost());
            workerNode.setPort(DockerUtils.getDockerPort());
        } else {
            workerNode.setType(WorkerNodeType.ACTUAL.value());
            workerNode.setHostName(NetUtils.getLocalAddress());
            workerNode.setPort(System.currentTimeMillis() + "-" + RandomUtils.nextInt(0, 100000));
        }
        workerNode.setLaunchDate(LocalDate.now());
        workerNode.setCreateTime(LocalDateTime.now());
        workerNode.setUpdateTime(LocalDateTime.now());
        return workerNode;
    }

}
